package com.bblocks.common.anti_reptile.data;

import com.bblocks.common.anti_reptile.config.AntiReptileProperties;
import com.bblocks.common.anti_reptile.config.bean.RuleComm;
import com.bblocks.common.anti_reptile.constant.AntiReptileConsts;
import com.bblocks.common.anti_reptile.constant.RuleTypeEnum;
import com.bblocks.common.anti_reptile.module.IpUserNumVo;
import com.bblocks.common.anti_reptile.module.RuleStatVO;
import com.bblocks.common.anti_reptile.module.RuleVO;
import com.bblocks.common.anti_reptile.rule.AbstractRuleData;
import com.bblocks.common.anti_reptile.rule.RuleData;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Lazy;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalField;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * <p>Project: bb-anti-reptile - RuleDataFromDb</p>
 * <p>描述：提取ip/user访问规则-简单版本平均/最高qps
 * 1、系统未提取到数据，走默认规则
 * 2、默认规则未配置 则无规则
 * 3、ip 用户数-未提取到按1计算
 *
 * 4、保存数据（2大类）
 * </p>
 *
 * @Author Zhao [125043150@qq.com]
 * @Date 2024/3/25 10:36
 * @Version 1.0
 * @since 8
 */
@ConditionalOnClass({ RedissonClient.class, JdbcTemplate.class})
@Slf4j
//@Component
public class RuleDataFromDb extends AbstractRuleData {

    @Autowired
    @Qualifier(AntiReptileConsts.JDBC_TEMP_ANTI)
    private JdbcTemplate jdbcTemplate;

    @PostConstruct
    public void init() {
        super.init();
        //启动线程，提取并计算数据
        log.info("启动线程定时同步数据(来源：db)！,时间：{}",getRunStartTime(this.getAntiReptileProperties()));

        if (this.syncOnStart()) {
            //初始执行提取数据
            this.getScheduledExecutorService().schedule(new TimerTask() {
                @Override
                public void run() {
                    allDatasSync(LocalDate.now().plusDays(-1));
                }
            }, 10_000, TimeUnit.MILLISECONDS);
        }


        //启动定时器
        this.getScheduledExecutorService().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                allDatasSync(LocalDate.now().plusDays(-1));
            }
        }, getRunStartTimeSeconds(this.getAntiReptileProperties()), 24*60*60,TimeUnit.SECONDS);
    }

    @PreDestroy
    public void destroy() {
        this.getScheduledExecutorService().shutdownNow();
    }


    protected void allDatas(@NonNull LocalDate now) {
        log.info("同步流量控制数据(来源：db)！");
        int pageSize = this.getAntiReptileProperties().getDb().getSyncBatchNo();
        processData(pageSize);
    }

    /**
     * 后期可以优化成多线程
     * @param pageSize
     */
    private void processData(int pageSize){
        saveUrlStat(pageSize);

        saveIpStat(pageSize);
    }

    private long saveUrlStat(int pageSize){
        int total = 0;
        long lastId = 0L;
        while (true) {
            List<RuleStatVO> urlStatVOs = jdbcTemplate.query(sql_url_sum, new BeanPropertyRowMapper<>(RuleStatVO.class),lastId, pageSize);
            if (!urlStatVOs.isEmpty()) {
                urlStatVOs.forEach(vo -> {
                    this.saveRule(vo);
                });
                lastId = urlStatVOs.get(urlStatVOs.size()-1).getId();
                total += urlStatVOs.size();
            } else
                break;
        }
        log.info("同步共提取到url统计数据:{}", total);
        return total;
    }

    private int saveIpStat(int pageSize){
        int total = 0;
        long lastId = 1;
        while (true) {
            List<IpUserNumVo> ipStatVOs = jdbcTemplate.query(sql_ip_sum, new BeanPropertyRowMapper<>(IpUserNumVo.class), lastId,pageSize);
            if (!ipStatVOs.isEmpty()) {
                ipStatVOs.forEach(vo -> {
                    this.saveIpUser(vo);
                });
                lastId = ipStatVOs.get(ipStatVOs.size()-1).getId();
                total += ipStatVOs.size();
            } else
                break;
        }
        log.info("同步共提取到ip统计数据:{}", total);
        return total;
    }



}
